﻿#region License
/* Copyright (C) 2009 Tim Coulter
 * 
 * This file is part of ExtremeML.
 * 
 * ExtremeML is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License, as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
*/
#endregion

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using ExtremeML.Core;
using ExtremeML.Sdk.Gdi;

namespace ExtremeML.Packaging
{
	// This is a partial class that adds custom functionality to its auto-generated partner.
	public sealed partial class ImagePartWrapper
	{
		#region Custom Properties


		#endregion
		#region Custom Methods

		/// <summary>
		/// Stores the passed image to the underlying stream of the wrapped image part.
		/// </summary>
		/// <param name="image">An <see cref="Image"/> to be stored.</param>
		public void SetImage(
			Image image)
		{
			if (image == null)
			{
				Remove();
			}
			else
			{
				using (var stream = Wrapped.GetStream(FileMode.Create, FileAccess.Write))
				{
					image.Save(stream, Imaging.GetImageCodecInfo(Wrapped.ContentType), Imaging.GetEncoderParameters(100));
				}
			}
		}

		/// <summary>
		/// Returns the image from the underlying stream of the wrapped image part.
		/// </summary>
		/// <returns>A <see cref="Bitmap"/> constructed from the underlying steam data.</returns>
		public Bitmap GetImage()
		{
			using (var stream = Wrapped.GetStream(FileMode.Open, FileAccess.Read))
			{
				if (stream.Length > 0)
				{
					// This convoluted duplication technique is necessitated by the fact that
					// images populated from a stream require ongoing access to that stream.
					// See: http://support.microsoft.com/?id=814675
					var original = new Bitmap(stream);
					var result = Imaging.CopyImage(original);
					original.Dispose();
					return result;
				}
				else
				{
					return null;
				}
			}
		}

		#endregion
		#region Overrides


		#endregion
		#region Implementation Methods


		#endregion
		#region Static Methods

		/// <summary>
        /// Returns an <see cref="ImagePart"/> populated with the default content.
		/// </summary>
		/// <param name="container">The parent <see cref="OpenXmlPartContainer"/> instance.</param>
        /// <param name="args">A parameter array of <see cref="object"/> containing member initialization arguments.</param>
        /// <returns>An <see cref="ImagePart"/> populated with default content.</returns>
        /// <remarks>
        /// The first member of <paramref name="args"/> must be an <see cref="ImageFormat"/> that specifies the format of the image that will be stored in the new <see cref="ImagePart"/>.
        /// </remarks>
		internal static new ImagePart CreateCustomDefaultPart(
			OpenXmlPartContainer container,
            params object[] args)
		{
            Utility.ValidateParamsArgument(0, typeof(ImageFormat), args);

		    var partType = GetImagePartType((ImageFormat)args[0]);
            
            if (container is WorksheetPart)
			{
                return ((WorksheetPart)container).AddImagePart(partType);
			}
			else if (container is ThemePart)
			{
                return ((ThemePart)container).AddImagePart(partType);
			}
            else if (container is VmlDrawingPart)
            {
                return ((VmlDrawingPart)container).AddImagePart(partType);
            }

			return null;
		}

        /// <summary>
        /// Returns an <see cref="ImagePartType"/> enum value that represents the specified <see cref="ImageFormat"/>.
        /// </summary>
        private static ImagePartType GetImagePartType(
            ImageFormat format)
        {
            if (format.Guid.Equals(ImageFormat.Bmp.Guid))
            {
                return ImagePartType.Bmp;
            }
            else if (format.Guid.Equals(ImageFormat.Emf.Guid))
            {
                return ImagePartType.Emf;
            }
            else if (format.Guid.Equals(ImageFormat.Gif.Guid))
            {
                return ImagePartType.Gif;
            }
            else if (format.Guid.Equals(ImageFormat.Icon.Guid))
            {
                return ImagePartType.Icon;
            }
            else if (format.Guid.Equals(ImageFormat.Jpeg.Guid))
            {
                return ImagePartType.Jpeg;
            }
            else if (format.Guid.Equals(ImageFormat.Png.Guid))
            {
                return ImagePartType.Png;
            }
            else if (format.Guid.Equals(ImageFormat.Tiff.Guid))
            {
                return ImagePartType.Tiff;
            }
            else if (format.Guid.Equals(ImageFormat.Wmf.Guid))
            {
                return ImagePartType.Wmf;
            }
            else
            {
                throw new ArgumentException("Unsupported image format specified.");
            }
        }

        #endregion
	}
}
